package com.vains.config.security;

import com.vains.enumeration.ResultEnum;
import com.vains.io.JsonUtils;
import com.vains.service.impl.UserDetailsServiceImpl;
import com.vains.system.model.Result;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Configuration
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final PasswordEncoder passwordEncoder;

    private final UserDetailsServiceImpl userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/oauthPermission/hasAuth").permitAll()
                .antMatchers("/oauth/**").permitAll()
                .antMatchers("/login*").permitAll()
                // .anyRequest().access("hasAuthority('')")
                .anyRequest().access("@oauthPermissionServiceImpl.hasPermission()")    //所有请求必须登录后访问
                .and().exceptionHandling().authenticationEntryPoint(this::authenticationHandler)
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().formLogin().failureHandler(this::authenticationHandler);/*
                .loginPage("/login")
                .failureUrl("/login?error")
                .permitAll()    //登录页面、错误页面可以直接访问
                .and()
                .logout()
                .permitAll();      //注销请求可以直接访问*/

    }

    private void authenticationHandler(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException ex) {
        response.setContentType("application/json; charset=utf-8");
        Result<String> result = new Result<>(ResultEnum.NO_LOGIN.getCode(), false, ResultEnum.NO_LOGIN.getMessage(), null);
        try {
            response.getWriter().println(JsonUtils.objectCovertToJson(result));
        } catch (IOException e) {
            log.error("无权限提醒时响应失败! 原因: ", e);
        }
    }

    /**
     * 不定义没有password grant_type
     * @return AuthenticationManager
     * @throws Exception 异常信息
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}